import createElement from './createElement'
import setFn from '../lifecycle/setFn';
function patch2(oldVnode,newVnode,vm){
  console.log(newVnode)
  console.log(oldVnode)
  //类型不同，直接替换
  if(!oldVnode){
    newVnode.elm = createelmVnode(newVnode);
    vm.vnode = newVnode;
    var child = vm.$el.lastElementChild;  
    while (child) { 
      vm.$el.removeChild(child); 
      child = vm.$el.lastElementChild; 
    } 
    vm.$el.appendChild(createelmVnode(newVnode))
    setFn(vm);
    return
  }
  if(oldVnode.tag !==newVnode.tag){
    return oldVnode.elm.parentNode.replaceChild(
      createelmVnode(newVnode),
      oldVnode.elm
    )
  }
  if(oldVnode.tag =='input'){
    console.log(oldVnode.props)
  }
  //类型相同，换文本 废弃
  if(oldVnode.text){
    if(oldVnode.text == newVnode.text)return
    // var parent = oldVnode.elm.parentNode;
    // parent.appendChild(createelmVnode(newVnode))
    // parent.removeChild(oldVnode.elm)
    return oldVnode.elm.textContent = newVnode.text;
  }

  let elm = newVnode.elm = oldVnode.elm;
  //更新属性
  updateProper(newVnode,oldVnode.props);

  let oldChildren = oldVnode.children;
  let newChildren = newVnode.children;
  if(oldChildren.length > 0 && newChildren.length > 0){
    updateChildren(elm,oldChildren,newChildren);
  }else if(oldChildren.length >0){
    //old有new无
    elm.innerHTML = '';
  }else if(newChildren.length >0){
    for (let index = 0; index < newChildren.length; index++) {
      elm.appendChild(
        createelmVnode(newChildren[index])
      )
      
    }
  }

}
function updateProper(newVnode, oldProps = {}) {
  let elm = newVnode.elm // 真实的DOM元素
  let newProps = newVnode.props // 当前虚拟节点中的属性
  // 老的里面有 新的里面没有 这个属性被移除了
  for (let oldPropName in oldProps) {
      if (!newProps[oldPropName]) {
          delete elm[oldPropName]
      }
  }
  let newStyleObj = newProps.style || {}
  let oldStyleObj = oldProps.style || {}
  // 如果老的里面没有 新的里面有

  for (let propName in oldStyleObj) {
      if (!newStyleObj[propName]) {
          elm.style[propName] = ''
      }
  }
  // 如果属性是style
  for (let newPropsName in newProps) {
      // 如果当前是style属性 取出来赋值给真实的DOM元素
      if (newPropsName == 'style') {
          let styleObj = newProps.style;
          for (let s in styleObj) {
              elm.style[s] = styleObj[s];
          }
      } else if(newPropsName =='on') {
        // const on = newProps[newPropsName]
        // for(let key in on){
        //   elm.addEventListener(key,()=>{
        //     on[key].call(vm);
        //   })
        // }
      }else{
        elm.setAttribute(newPropsName,newProps[newPropsName]) 
      }
  }

}
function createelmVnode(vnode) {
  let {
      key,
      props,
      children,
      text,
      tag
  } = vnode
  // 传递了类型 说明是一个标签
  if (typeof tag === 'string') {
      // 建立虚拟节点和真实元素一个关系 后面可以用来更新真实DOM
      vnode.elm = document.createElement(tag)
      updateProper(vnode,undefined,vm)
      children.forEach(childVnode => render(childVnode, vnode.elm))
  } else {
      // 文本
      vnode.elm = document.createTextNode(text)
  }
  return vnode.elm
}
function updateChildren(parent,oldChildren,newChildren,vm){
  // console.log(oldChildren)
  // console.log(newChildren)
  if(oldChildren.tag ===undefined && newChildren===undefined){
    return oldChildren.text = newChildren.text;
  }
  let oldStartIndex = 0;
  let oldStartVnode = oldChildren[0];
  let oldEndIndex = oldChildren.length - 1;
  let oldEndVnode = oldChildren[oldEndIndex];
  let map = keyMapByIndex(oldChildren)
  let newStartIndex = 0;
  let newStartVnode = newChildren[0];
  let newEndIndex = newChildren.length - 1;
  let newEndVnode = newChildren[newEndIndex];
  //
  while(oldStartIndex <= oldEndIndex && newStartIndex<=newEndIndex){
    if(!oldStartVnode){
      oldStartVnode = oldChildren[++oldStartIndex]
    }else if(!oldEndVnode){
      oldEndVnode = oldChildren[--oldEndIndex]
    }else
    if(isSomeVnode(oldStartVnode,newStartVnode)){
      //标签和类型相同比较属性
      patch2(oldStartVnode,newStartVnode);
      oldStartVnode = oldChildren[++oldStartIndex];
      newStartVnode = newChildren[++newStartIndex];
    }else if(isSomeVnode(oldEndVnode,newEndVnode)){
      patch2(oldEndVnode,newEndVnode);
      oldEndVnode = oldChildren[--oldEndIndex];
      newEndVnode = newChildren[--newEndIndex];
    }else if(isSomeVnode(oldStartVnode,newEndVnode)){
      patch2(oldStartVnode,newEndVnode);
      parent.insertBefore(oldStartVnode.elm,oldEndVnode.elm.nextSibling);
      oldStartVnode = oldChildren[++oldStartIndex];
      newEndVnode = newChildren[--newEndIndex];
    }else if(isSomeVnode(oldEndVnode,newStartVnode)){
      patch2(oldEndVnode,newStartVnode);
      parent.insertBefore(oldEndVnode.elm,oldStartVnode.elm);
      oldEndVnode = oldChildren[--oldEndIndex];
      newStartVnode = newChildren[++newStartIndex]
    }else{              
      let index = map[newStartIndex.key];
      if(index == null){
        parent.insertBefore(createelmVnode(newStartVnode,oldStartVnode.elm))
      }else {
        let toMoveNode = oldChildren[index]
        patch2(toMoveNode,newStartVnode);
        parent.insertBefore(toMoveNode.elm,oldStartVnode.elm);
        oldChildren[index] = undefined;
      }

      newStartVnode = newChildren[++newStartIndex];
    }

  }
  //多余节点
  if(newStartIndex <= newEndIndex){
    for (let index = newStartIndex; index < newEndIndex.length; index++) {
      // parent.appendChild(createelmVnode(newChildren[index]))
      let beforElement = newChildren[newEndIndex + 1] ==null ? null:
      newChildren[newEndIndex + 1].elm
      parent.insertBefore(createelmVnode(newChildren[index],beforElement))
    }
    
  }
  if(oldStartIndex<=oldEndIndex){
    for (let index = oldStartIndex; index < oldEndIndex.length; index++) {
      if(oldChildren[index]){
        parent.removeChild(oldChildren[index].elm);
      }
    }
  }
}
function keyMapByIndex(oldChildren){
  let map = {};
  for (let index = 0; index < oldChildren.length; index++) {
    let current = oldChildren[index];
    if(current.key){
      map[current.key] = index;
    }
    
  }
  return map;
}
function isSomeVnode(oldVnode,newVnode){
  return oldVnode.tag === newVnode.tag;
}
export function render(vnode, container) {
  // 通过这个方法可以将虚拟节点转化为真实节点
  let ele = createelmVnode(vnode)
  //  插入到容器
  container.appendChild(ele)
}
export {patch2}